home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / machack / Hacks97 / FinderDungeon.sit / Finder Dungeon / source code / ScriptableFinder.c < prev    next >
Text File  |  1997-06-28  |  32KB  |  764 lines

  1. // File by Leonard Rosenthol
  2.  
  3. #include <icons.h>
  4. #include <AppleEvents.h>
  5. #include <AERegistry.h>
  6. #include "FinderRegistry.h"
  7. #include "ScriptableFinder.h"
  8.  
  9. OSErr    convertfahtoAElist(FSSpecArrayHandle fah, AEDescList *selectionlist)
  10.  
  11. /*    A routine to convert the data contained within the passed FSSpecArrayHandle into an AEDescList
  12.     which can be passed as a parameter inside an Apple Event.
  13.  
  14.      Input:    fah - source FSSpecArrayHandle.
  15.      Input:    *selectionlist - result AEDescList (must be pre-created) passed by reference.
  16.  
  17.     Output:    error code that occured. */
  18.  
  19. {
  20.     short    result;
  21.  
  22.     result = noErr;
  23.     if (fah != nil) 
  24.     {
  25.         short    i, maxfah, count;
  26.  
  27.         count = 0;
  28.         maxfah = (GetHandleSize((Handle)fah) / sizeof(FSSpec));
  29.         for (i = 0; i < maxfah; i++)
  30.             if (result == noErr) 
  31.             {
  32.                 count++;
  33.                 if ((result = AEPutPtr(selectionlist, count, typeFSS, &(*fah)[i], sizeof(FSSpec))) != noErr) 
  34.                     count--;
  35.             }
  36.     }
  37.     return(result);
  38. }
  39.  
  40. OSErr    AddToFSSpecArrayHandle (FSSpec *f, FSSpecArrayHandle fah)
  41.  
  42. {
  43.     OSErr    result;
  44.     long    l;
  45.  
  46.     l = InlineGetHandleSize((Handle)fah);
  47.     SetHandleSize((Handle)fah, l + sizeof(FSSpec));
  48.     result = MemError();
  49.     if (result == noErr) 
  50.         BlockMoveData(f, (Ptr)((long)*fah + l), sizeof(FSSpec));
  51.     return(result);
  52. }
  53.  
  54. OSErr    GetFinderProcess (ProcessSerialNumber *finderpsn, Boolean shortcut)
  55.  
  56. /*    A routine to determine the process serial number of the Finder. It returns the result as a
  57.     parameter passed by reference. It also has a Boolean parameter which specifies whether or not
  58.     the returned process serial number will represent the Finder process serial number as
  59.     "kCurrentProcess" if it is the current process to allow a shortcut of the _GetNextEvent call
  60.     dependencies of processing an AppleEvent.
  61.  
  62.      Input:    shortcut - allow "kCurrentProcess" to be used if we are in the current process.
  63.      Input:    *finderpsn - result ProcessSerialNumber passed by reference.
  64.  
  65.     Output:    error code that occured. */
  66.  
  67. {
  68.     Boolean                result;
  69.     ProcessSerialNumber    psn, currentpsn;
  70.     ProcessInfoRec        pir;
  71.  
  72.     psn.highLongOfPSN = 0;
  73.     psn.lowLongOfPSN = kNoProcess;
  74.     pir.processInfoLength = sizeof(ProcessInfoRec);
  75.     pir.processName = nil;            // don't want these bits of information
  76.     pir.processAppSpec = nil;
  77.     while (GetNextProcess(&psn) == noErr) 
  78.         if (GetProcessInformation(&psn, &pir) == noErr) 
  79.             if ((pir.processType == kFinderType) && (pir.processSignature == kFinderSignature)) 
  80.             {
  81.                 if (shortcut && (GetCurrentProcess(¤tpsn) == noErr) && 
  82.                     (SameProcess(¤tpsn, &psn, &result) == noErr) && result) 
  83.                 {            // use the current process to shortcut the event dispatching
  84.                     finderpsn->highLongOfPSN = 0;
  85.                     finderpsn->lowLongOfPSN = kCurrentProcess;
  86.                 }
  87.                 else
  88.                     *finderpsn = psn;            // found the Finder's psn
  89.                 return(noErr);            // got the process serial number
  90.             }
  91.     return(procNotFound);            // got an error - not found
  92. }
  93.  
  94. Boolean    IsRelativeProcessSerialNumber (ProcessSerialNumber *psn)
  95.  
  96. /*    A simple routine which determines whether the process serial number given is a relative one.
  97.     This means that it isn't a number which refers to the process outright but rather refers to the
  98.     process because it's current.
  99.  
  100.      Input: psn - the ProcessSerialNumber to check.
  101.  
  102.     Output: Boolean result. */
  103.  
  104. {
  105.     return((psn->highLongOfPSN == 0) && (psn->lowLongOfPSN == kCurrentProcess));
  106. }
  107.  
  108. OSErr    GetScriptableFinderSelection (FSSpecArrayHandle *fah, Boolean usesystemmode)
  109.  
  110. /*    A routine to get the Finder's selection using the GetData Apple Event. It tries it's best to get
  111.     the result immediately and resorts to allowing the shortcut in the AESend routine where the
  112.     event is sent to the current process specified by "kCurrentProcess" in the ProcessSerialNumber.
  113.  
  114.      Input:    *fah - result FSSpecArrayHandle passed by reference. Nil if no items selected.
  115.      Input:    usesystemmode - a Boolean which determines whether the system's PPC port will be used.
  116.  
  117.     Output:    error code that occured. */
  118.  
  119. {
  120.     short                errnum;
  121.     Boolean                fiddlewithA5;            // See below for the usage of the A5 variables
  122.     long                saveA5;
  123.     OSType                selectiondescriptor, resultdescriptor;
  124.     ProcessSerialNumber    targetpsn;
  125.     AEDesc                targetaddress, selectiondesc, nulldesc, directdesc, requestdesc, listdesc;
  126.     AppleEvent            myae, myreply;
  127.  
  128.     *fah = nil;            // make sure we have a valid empty result
  129.     selectiondescriptor = pSelection;
  130.     resultdescriptor = typeFSS;
  131.     if (GetFinderProcess(&targetpsn, kRelativeFinderPSN) == noErr) 
  132.     {
  133. //        if (usesystemmode) 
  134. //            TurnSystemModeOn();            // you really DON'T want to do this
  135.     
  136. /*    Here's a good problem. If we shortcut the Apple Event processing mechanism by using the relative
  137.     kCurrentProcess in the process serial number to get to the Finder's 'Get Data' routine this
  138.     works fine if the A5 register is that of the Finder. However, Magic Menu calls this routine from
  139.     a patch within _MenuKey or _MenuSelect and the Process Manager patches over these routines. It
  140.     puts its own A5 in but doesn't modify the low-memory global. So... just to be sure that we've
  141.     got the correct A5 we'll restore the A5 world if we're using the relative process serial number.
  142.     Otherwise the Apple Event is sent via the Event Manager and the A5 register will be correct. */
  143.  
  144.         fiddlewithA5 = IsRelativeProcessSerialNumber(&targetpsn);
  145.         if (fiddlewithA5) 
  146.             saveA5 = SetCurrentA5();
  147.  
  148. /*    The following if statement is the guts of the GetScriptableFinderSelection routine. It
  149.     composes the AppleEvent and fills in all the correct parameters and options. Then it calls
  150.     the Finder to get the information and extracts the returned data from the descriptor list.
  151.     It puts the items in an FSSpecArrayHandle. If an error occurs it just returns nil. Note that
  152.     this routine uses an assignment followed by a comparison which although not good logic allows
  153.     this routine to be compressed into a single if statement linked with terminating and comparisons
  154.     whilst collecting the error number that occurred. */
  155.  
  156.         if (((errnum = AECreateDesc(typeProcessSerialNumber, &targetpsn, sizeof(targetpsn), &targetaddress)) == noErr) && 
  157.             ((errnum = AECreateAppleEvent(kAECoreSuite, kAEGetData, &targetaddress, kAutoGenerateReturnID, kAnyTransactionID, &myae)) == noErr) && 
  158.             ((errnum = AEDisposeDesc(&targetaddress)) == noErr) && 
  159.             ((errnum = AECreateDesc(typeType, &selectiondescriptor, sizeof(selectiondescriptor), &selectiondesc)) == noErr) && 
  160.             ((errnum = AECreateDesc(typeNull, nil, 0, &nulldesc)) == noErr) && 
  161.             ((errnum = CreateObjSpecifier(cProperty, &nulldesc, formPropertyID, &selectiondesc, TRUE, &directdesc)) == noErr) && 
  162.             ((errnum = AEPutParamDesc(&myae, keyDirectObject, &directdesc)) == noErr) && 
  163.             ((errnum = AEDisposeDesc(&selectiondesc)) == noErr) && 
  164.             ((errnum = AEDisposeDesc(&nulldesc)) == noErr) && 
  165.             ((errnum = AEDisposeDesc(&directdesc)) == noErr) && 
  166.             ((errnum = AECreateDesc(typeType, &resultdescriptor, sizeof(resultdescriptor), &selectiondesc)) == noErr) && 
  167.             ((errnum = AECoerceDesc(&selectiondesc, typeAEList, &requestdesc)) == noErr) && 
  168.             ((errnum = AEDisposeDesc(&selectiondesc)) == noErr) && 
  169.             ((errnum = AEPutParamDesc(&myae, keyAERequestedType, &requestdesc)) == noErr) && 
  170.             ((errnum = AEDisposeDesc(&requestdesc)) == noErr) && 
  171.             ((errnum = AESend(&myae, &myreply, kAEWaitReply, kAENeverInteract, kAEDefaultTimeout, nil, nil)) == noErr) && 
  172.             ((errnum = AEGetParamDesc(&myreply, keyAEResult, typeAEList, &listdesc)) == noErr) && 
  173.             ((errnum = AEDisposeDesc(&myreply)) == noErr) && 
  174.             ((errnum = AEDisposeDesc(&myae)) == noErr)) 
  175.         {            // Whew! We passed the test. Do we get a cookie now?
  176.             short                i;
  177.             long                count;
  178.             AEKeyword            returnedkeyword;
  179.             AEDesc                resultdesc;
  180.  
  181. //    Convert result AEDesc list of FSSpecs to our own internal FSSpecArrayHandle
  182.  
  183.             *fah = (FSSpecArrayHandle)NewHandle(0);
  184.             if ((errnum = AECountItems(&listdesc, &count)) == noErr) 
  185.                 for (i = 1; i <= count; i++)
  186.                     if ((errnum == noErr) && (errnum = AEGetNthDesc(&listdesc, i, typeFSS, &returnedkeyword, &resultdesc)) == noErr) 
  187.                     {
  188.                         HLock(resultdesc.dataHandle);
  189.                         errnum = AddToFSSpecArrayHandle(*(FSSpecHandle)resultdesc.dataHandle, *fah);
  190.                         HUnlock(resultdesc.dataHandle);
  191.                         if (errnum == noErr) 
  192.                             errnum = AEDisposeDesc(&resultdesc);
  193.                     }
  194.             if (errnum == noErr) 
  195.                 errnum = AEDisposeDesc(&listdesc);
  196.         }
  197.         if (fiddlewithA5) 
  198.             SetA5(saveA5);            // fix it up for crying out loud!
  199. //        if (usesystemmode) 
  200. //            TurnSystemModeOff();            // we really DIDN'T want to do this
  201.     }
  202.     return(errnum);            // the result
  203. }
  204.  
  205. OSErr    SetScriptableFinderSelection (FSSpecArrayHandle fah, Boolean usesystemmode, 
  206.             AESendMode sendmode)
  207.  
  208. /*    A routine to set the Finder's selection using the GetData Apple Event. It tries it's best to get
  209.     the result immediately and resorts to allowing the shortcut in the AESend routine where the
  210.     event is sent to the current process specified by "kCurrentProcess" in the ProcessSerialNumber.
  211.  
  212.      Input:    fah - FSSpecArrayHandle which contains the items to select. Nil if no selection.
  213.      Input:    usesystemmode - a Boolean which determines whether the system's PPC port will be used.
  214.      Input: sendmode - which mode to send the Apple Event to the Finder.
  215.  
  216.     Output:    error code that occured. */
  217.  
  218. {
  219.     short                errnum;
  220.     Boolean                fiddlewithA5;            // See below for the usage of the A5 variables
  221.     long                saveA5;
  222.     OSType                selectiondescriptor, resultdescriptor;
  223.     ProcessSerialNumber    targetpsn;
  224.     AEDesc                targetaddress, selectiondesc, nulldesc, directdesc;
  225.     AEDescList            selectionlist;
  226.     AppleEvent            myae, myreply;
  227.  
  228.     selectiondescriptor = pSelection;
  229.     resultdescriptor = typeFSS;
  230.     if (GetFinderProcess(&targetpsn, kRelativeFinderPSN) == noErr) 
  231.     {
  232. //        if (usesystemmode) 
  233. //            TurnSystemModeOn();            // you really DON'T want to do this
  234.         fiddlewithA5 = IsRelativeProcessSerialNumber(&targetpsn);
  235.         if (fiddlewithA5) 
  236.             saveA5 = SetCurrentA5();
  237.         if (((errnum = AECreateDesc(typeProcessSerialNumber, &targetpsn, sizeof(targetpsn), &targetaddress)) == noErr) && 
  238.             ((errnum = AECreateAppleEvent(kAECoreSuite, kAESetData, &targetaddress, kAutoGenerateReturnID, kAnyTransactionID, &myae)) == noErr) && 
  239.             ((errnum = AEDisposeDesc(&targetaddress)) == noErr) && 
  240.             ((errnum = AECreateDesc(typeType, &selectiondescriptor, sizeof(selectiondescriptor), &selectiondesc)) == noErr) && 
  241.             ((errnum = AECreateDesc(typeNull, nil, 0, &nulldesc)) == noErr) && 
  242.             ((errnum = CreateObjSpecifier(cProperty, &nulldesc, formPropertyID, &selectiondesc, TRUE, &directdesc)) == noErr) && 
  243.             ((errnum = AEPutParamDesc(&myae, keyDirectObject, &directdesc)) == noErr) && 
  244.             ((errnum = AEDisposeDesc(&selectiondesc)) == noErr) && 
  245.             ((errnum = AEDisposeDesc(&nulldesc)) == noErr) && 
  246.             ((errnum = AEDisposeDesc(&directdesc)) == noErr) && 
  247.             ((errnum = AECreateList(nil, 0, FALSE, &selectionlist)) == noErr) && 
  248.             ((errnum = convertfahtoAElist(fah, &selectionlist)) == noErr) && 
  249.             ((errnum = AEPutParamDesc(&myae, keyAEData, &selectionlist)) == noErr) && 
  250.             ((errnum = AEDisposeDesc(&selectionlist)) == noErr) && 
  251.             ((errnum = AESend(&myae, &myreply, sendmode, kAENeverInteract, kAEDefaultTimeout, nil, nil)) == noErr) && 
  252.             ((errnum = AEDisposeDesc(&myreply)) == noErr)) 
  253.             errnum = AEDisposeDesc(&myae);
  254.         if (fiddlewithA5) 
  255.             SetA5(saveA5);            // fix it up for crying out loud!
  256. //        if (usesystemmode) 
  257. //            TurnSystemModeOff();            // we really DIDN'T want to do this
  258.     }
  259.     return(errnum);            // the result
  260. }
  261.  
  262. OSErr    RevealScriptableFinderSelection (FSSpecArrayHandle fah, Boolean usesystemmode, 
  263.             AESendMode sendmode)
  264.  
  265. /*    A routine to reveal the contents of a given FSSpecArrayHandle using the new kAEMakeObjectVisible
  266.     Apple Event understood by the scriptable Finder. This event is better than the old 'reveal'
  267.     event as the old event doesn't deselect any previously selected items (and therefore is to be
  268.     considered buggy).
  269.  
  270.      Input:    fah - FSSpecArrayHandle which contains the items to reveal. Nil if nothing to reveal.
  271.      Input:    usesystemmode - a Boolean which determines whether the system's PPC port will be used.
  272.      Input: sendmode - which mode to send the Apple Event to the Finder.
  273.  
  274.     Output:    error code that occured. */
  275.  
  276. {
  277.     short                errnum;
  278.     Boolean                fiddlewithA5;            // See below for the usage of the A5 variables
  279.     long                saveA5;
  280.     ProcessSerialNumber    targetpsn;
  281.     AEDesc                targetaddress;
  282.     AEDescList            selectionlist;
  283.     AppleEvent            myae, myreply;
  284.  
  285.     if (GetFinderProcess(&targetpsn, kRelativeFinderPSN) == noErr) 
  286.     {
  287. //        if (usesystemmode) 
  288. //            TurnSystemModeOn();            // you really DON'T want to do this
  289.         fiddlewithA5 = IsRelativeProcessSerialNumber(&targetpsn);
  290.         if (fiddlewithA5) 
  291.             saveA5 = SetCurrentA5();
  292.         if (((errnum = AECreateDesc(typeProcessSerialNumber, &targetpsn, sizeof(targetpsn), &targetaddress)) == noErr) && 
  293.             ((errnum = AECreateAppleEvent(kAEMiscStandards, kAEMakeObjectsVisible, &targetaddress, kAutoGenerateReturnID, kAnyTransactionID, &myae)) == noErr) && 
  294.             ((errnum = AEDisposeDesc(&targetaddress)) == noErr) && 
  295.             ((errnum = AECreateList(nil, 0, FALSE, &selectionlist)) == noErr) && 
  296.             ((errnum = convertfahtoAElist(fah, &selectionlist)) == noErr) && 
  297.             ((errnum = AEPutParamDesc(&myae, keyDirectObject, &selectionlist)) == noErr) && 
  298.             ((errnum = AEDisposeDesc(&selectionlist)) == noErr) && 
  299.             ((errnum = AESend(&myae, &myreply, sendmode, kAENeverInteract, kAEDefaultTimeout, nil, nil)) == noErr) && 
  300.             ((errnum = AEDisposeDesc(&myreply)) == noErr)) 
  301.             errnum = AEDisposeDesc(&myae);
  302.         if (fiddlewithA5) 
  303.             SetA5(saveA5);            // fix it up for crying out loud!
  304. //        if (usesystemmode) 
  305. //            TurnSystemModeOff();            // we really DIDN'T want to do this
  306.     }
  307.     return(errnum);            // the result
  308. }
  309.  
  310. OSErr    OpenScriptableFinderSelection (FSSpecArrayHandle fah, Boolean usesystemmode, 
  311.             AESendMode sendmode, FSSpec *usingf)
  312.  
  313. /*    A routine to open the items in a given FSSpecArrayHandle using the specified FSSpec.
  314.  
  315.      Input:    fah - FSSpecArrayHandle which contains the items to open. Nil if nothing to open.
  316.      Input:    usesystemmode - a Boolean which determines whether the system's PPC port will be used.
  317.      Input: sendmode - which mode to send the Apple Event to the Finder.
  318.      Input: *usingf - the optional FSSpec which is designated to open the items.
  319.  
  320.     Output:    error code that occured. */
  321.  
  322. {
  323.     short                errnum;
  324.     Boolean                fiddlewithA5;            // See below for the usage of the A5 variables
  325.     long                saveA5;
  326.     ProcessSerialNumber    targetpsn;
  327.     AEDesc                targetaddress;
  328.     AEDescList            selectionlist;
  329.     AppleEvent            myae, myreply;
  330.  
  331.     if (GetFinderProcess(&targetpsn, kRelativeFinderPSN) == noErr) 
  332.     {
  333. //        if (usesystemmode) 
  334. //            TurnSystemModeOn();            // you really DON'T want to do this
  335.         fiddlewithA5 = IsRelativeProcessSerialNumber(&targetpsn);
  336.         if (fiddlewithA5) 
  337.             saveA5 = SetCurrentA5();
  338.         if (((errnum = AECreateDesc(typeProcessSerialNumber, &targetpsn, sizeof(targetpsn), &targetaddress)) == noErr) && 
  339.             ((errnum = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, &targetaddress, kAutoGenerateReturnID, kAnyTransactionID, &myae)) == noErr) && 
  340.             ((errnum = AEDisposeDesc(&targetaddress)) == noErr) && 
  341.             ((errnum = AECreateList(nil, 0, FALSE, &selectionlist)) == noErr) && 
  342.             ((errnum = convertfahtoAElist(fah, &selectionlist)) == noErr) && 
  343.             ((errnum = AEPutParamDesc(&myae, keyDirectObject, &selectionlist)) == noErr) && 
  344.             ((errnum = AEDisposeDesc(&selectionlist)) == noErr)) 
  345.             {
  346.                 if (usingf != nil) 
  347.                 {            // add the using parameter
  348.                     AEDesc    usingdesc;
  349.  
  350.                     if (((errnum = AECreateDesc(typeFSS, usingf, sizeof(FSSpec), &usingdesc)) == noErr) && 
  351.                         ((errnum = AEPutParamDesc(&myae, keyAEUsing, &usingdesc)) == noErr)) 
  352.                         errnum = AEDisposeDesc(&usingdesc);
  353.                 }
  354.                 if ((errnum == noErr) && 
  355.                     ((errnum = AESend(&myae, &myreply, sendmode, kAENeverInteract, kAEDefaultTimeout, nil, nil)) == noErr) && 
  356.                     ((errnum = AEDisposeDesc(&myreply)) == noErr)) 
  357.                     errnum = AEDisposeDesc(&myae);
  358.             }
  359.         if (fiddlewithA5) 
  360.             SetA5(saveA5);            // fix it up for crying out loud!
  361. //        if (usesystemmode) 
  362. //            TurnSystemModeOff();            // we really DIDN'T want to do this
  363.     }
  364.     return(errnum);            // the result
  365. }
  366.  
  367. OSErr    PrintScriptableFinderSelection (FSSpecArrayHandle fah, Boolean usesystemmode, 
  368.             AESendMode sendmode)
  369.  
  370. /*    A routine to print the items in a given FSSpecArrayHandle.
  371.  
  372.      Input:    fah - FSSpecArrayHandle which contains the items to open. Nil if nothing to open.
  373.      Input:    usesystemmode - a Boolean which determines whether the system's PPC port will be used.
  374.      Input: sendmode - which mode to send the Apple Event to the Finder.
  375.  
  376.     Output:    error code that occured. */
  377.  
  378. {
  379.     short                errnum;
  380.     Boolean                fiddlewithA5;            // See below for the usage of the A5 variables
  381.     long                saveA5;
  382.     ProcessSerialNumber    targetpsn;
  383.     AEDesc                targetaddress;
  384.     AEDescList            selectionlist;
  385.     AppleEvent            myae, myreply;
  386.  
  387.     if (GetFinderProcess(&targetpsn, kRelativeFinderPSN) == noErr) 
  388.     {
  389. //        if (usesystemmode) 
  390. //            TurnSystemModeOn();            // you really DON'T want to do this
  391.         fiddlewithA5 = IsRelativeProcessSerialNumber(&targetpsn);
  392.         if (fiddlewithA5) 
  393.             saveA5 = SetCurrentA5();
  394.         if (((errnum = AECreateDesc(typeProcessSerialNumber, &targetpsn, sizeof(targetpsn), &targetaddress)) == noErr) && 
  395.             ((errnum = AECreateAppleEvent(kCoreEventClass, kAEPrintDocuments, &targetaddress, kAutoGenerateReturnID, kAnyTransactionID, &myae)) == noErr) && 
  396.             ((errnum = AEDisposeDesc(&targetaddress)) == noErr) && 
  397.             ((errnum = AECreateList(nil, 0, FALSE, &selectionlist)) == noErr) && 
  398.             ((errnum = convertfahtoAElist(fah, &selectionlist)) == noErr) && 
  399.             ((errnum = AEPutParamDesc(&myae, keyDirectObject, &selectionlist)) == noErr) && 
  400.             ((errnum = AEDisposeDesc(&selectionlist)) == noErr) && 
  401.             ((errnum = AESend(&myae, &myreply, sendmode, kAENeverInteract, kAEDefaultTimeout, nil, nil)) == noErr) && 
  402.             ((errnum = AEDisposeDesc(&myreply)) == noErr)) 
  403.             errnum = AEDisposeDesc(&myae);
  404.         if (fiddlewithA5) 
  405.             SetA5(saveA5);            // fix it up for crying out loud!
  406. //        if (usesystemmode) 
  407. //            TurnSystemModeOff();            // we really DIDN'T want to do this
  408.     }
  409.     return(errnum);            // the result
  410. }
  411.  
  412. OSErr    UpdateScriptableFinderContainer (FSSpec *f, Boolean usesystemmode, AESendMode sendmode)
  413.  
  414. /*    A routine to update the contents of a Finder window immediately. The Finder normally updates
  415.     any changes it discovers in modification date of a folder by scanning every 5-10 seconds in idle
  416.     time. Sometimes this delay can be somewhat disconcerting for a Macintosh user who expects an
  417.     icon to appear instantly. To circumvent this you should send the Finder an update event
  418.     specifying which container to update.
  419.  
  420.      Input:    *f - The FSSpec of the folder to be updated.
  421.      Input:    usesystemmode - a Boolean which determines whether the system's PPC port will be used.
  422.      Input: sendmode - which mode to send the Apple Event to the Finder.
  423.  
  424.     Output:    error code that occured. */
  425.  
  426. {
  427.     short                errnum;
  428.     Boolean                fiddlewithA5;            // See below for the usage of the A5 variables
  429.     long                saveA5;
  430.     ProcessSerialNumber    targetpsn;
  431.     AEDesc                targetaddress, updatedesc;
  432.     AppleEvent            myae, myreply;
  433.  
  434.     if (GetFinderProcess(&targetpsn, kRelativeFinderPSN) == noErr) 
  435.     {
  436. //        if (usesystemmode) 
  437. //            TurnSystemModeOn();            // you really DON'T want to do this
  438.         fiddlewithA5 = IsRelativeProcessSerialNumber(&targetpsn);
  439.         if (fiddlewithA5) 
  440.             saveA5 = SetCurrentA5();
  441.         if (((errnum = AECreateDesc(typeProcessSerialNumber, &targetpsn, sizeof(targetpsn), &targetaddress)) == noErr) && 
  442.             ((errnum = AECreateAppleEvent(kAEFinderSuite, kAEUpdate, &targetaddress, kAutoGenerateReturnID, kAnyTransactionID, &myae)) == noErr) && 
  443.             ((errnum = AEDisposeDesc(&targetaddress)) == noErr) && 
  444.             ((errnum = AECreateDesc(typeFSS, f, sizeof(FSSpec), &updatedesc)) == noErr) && 
  445.             ((errnum = AEPutParamDesc(&myae, keyDirectObject, &updatedesc)) == noErr) && 
  446.             ((errnum = AEDisposeDesc(&updatedesc)) == noErr) && 
  447.             ((errnum = AESend(&myae, &myreply, sendmode, kAENeverInteract, kAEDefaultTimeout, nil, nil)) == noErr) && 
  448.             ((errnum = AEDisposeDesc(&myreply)) == noErr)) 
  449.             errnum = AEDisposeDesc(&myae);
  450.         if (fiddlewithA5) 
  451.             SetA5(saveA5);            // fix it up for crying out loud!
  452. //        if (usesystemmode) 
  453. //            TurnSystemModeOff();            // we really DIDN'T want to do this
  454.     }
  455.     return(errnum);            // the result
  456. }
  457.  
  458. static    pascal    OSErr    addIconsToAERecord (ResType theType, Handle *theIcon, void *yourDataPtr)
  459.  
  460. {
  461.     return(AEPutKeyPtr((AERecord*)yourDataPtr, theType, theType, **theIcon, GetHandleSize(*theIcon)));
  462. }
  463.  
  464. IconActionUPP iconActionProc = nil;
  465. OSErr    SetScriptableFinderFileIcon (FSSpec *f, Handle iconFamily, Boolean usesystemmode, 
  466.                                         AESendMode sendmode)
  467.  
  468. /*    
  469.  
  470.      Input:    f - FSSpec which contains the item to change the custom icon of.
  471.      Input:    usesystemmode - a Boolean which determines whether the system's PPC port will be used.
  472.      Input: sendmode - which mode to send the Apple Event to the Finder.
  473.  
  474.     Output:    error code that occured. */
  475.  
  476. {
  477.     short                errnum;
  478.     OSType                icondescriptor;
  479.     ProcessSerialNumber    targetpsn;
  480.     AEDesc                targetaddress, propdesc, filedesc, directdesc, icondesc, nulldesc, targetdesc;
  481.     AppleEvent            myae;
  482.  
  483.     nulldesc.descriptorType = typeNull;
  484.     nulldesc.dataHandle = nil;
  485.  
  486.     icondescriptor = pIconBitmap;
  487.     if (GetFinderProcess(&targetpsn, kAbsoluteFinderPSN) == noErr) 
  488.     {
  489. //        if (usesystemmode)     TurnSystemModeOn();            // you really DON'T want to do this
  490.         
  491.         // create the icon family descriptor
  492.         {
  493.             OSErr    err;
  494.             
  495.             if ((err = AECreateList(nil, 0, true, &icondesc)) == noErr) {
  496.                 if(!iconActionProc)
  497.                     iconActionProc = NewIconActionProc(addIconsToAERecord);
  498.                 err = ForEachIconDo(iconFamily, svAllAvailableData, iconActionProc, (void *)&icondesc);
  499.                 err = AECoerceDesc(&icondesc, cIconFamily, &icondesc);
  500.             }
  501.         }
  502.         
  503.         if ((errnum = AECreateDesc(typeProcessSerialNumber, &targetpsn, sizeof(targetpsn), &targetaddress)) == noErr) {
  504.             if ((errnum = AECreateAppleEvent(kAECoreSuite, kAESetData, &targetaddress, kAutoGenerateReturnID, kAnyTransactionID, &myae)) == noErr) {
  505.                 if ((errnum = AECreateDesc(typeType, &icondescriptor, sizeof(DescType), &propdesc)) == noErr) {
  506.                     AliasHandle    targetAlias;
  507.                     NewAlias(nil, f, &targetAlias);
  508.                     HLock((Handle)targetAlias);
  509.                     if ((errnum = AECreateDesc(typeAlias, *targetAlias, GetHandleSize((Handle)targetAlias), &filedesc)) == noErr) {
  510.                         if ((errnum = CreateObjSpecifier(typeWildCard, &nulldesc, typeAlias,&filedesc, TRUE, &targetdesc)) == noErr) {
  511.                             if ((errnum = CreateObjSpecifier(cProperty, &targetdesc, formPropertyID, &propdesc, TRUE, &directdesc)) == noErr) {
  512.                                 if ((errnum = AEPutParamDesc(&myae, keyDirectObject, &directdesc)) == noErr) {
  513.                                     if ((errnum = AEPutParamDesc(&myae, keyAEData, &icondesc)) == noErr) {
  514.                                         errnum = AESend(&myae, nil, sendmode, kAENeverInteract, kAEDefaultTimeout, nil, nil);
  515.                                     }
  516.                                 }
  517.                                 AEDisposeDesc(&directdesc);
  518.                             }
  519.                         }
  520.                         AEDisposeDesc(&filedesc);
  521.                     }
  522.                     HUnlock((Handle)targetAlias);
  523.                     AEDisposeDesc(&propdesc);
  524.                 }
  525.                 AEDisposeDesc(&myae);
  526.             }
  527.             AEDisposeDesc(&targetaddress);
  528.         }
  529.         
  530.         AEDisposeDesc(&icondesc);
  531.         
  532. //        if (usesystemmode)     TurnSystemModeOff();            // we really DIDN'T want to do this
  533.     }
  534.     return(errnum);            // the result
  535. }
  536.  
  537. OSErr    GetScriptableFinderFileIcon (FSSpec *f, Boolean usesystemmode, AESendMode sendmode, Handle *iconFamily)
  538.  
  539. /*    
  540.  
  541.      Input:    f - FSSpec which contains the item to change the custom icon of.
  542.      Input:    usesystemmode - a Boolean which determines whether the system's PPC port will be used.
  543.      Input: sendmode - which mode to send the Apple Event to the Finder.
  544.  
  545.     Output:    error code that occured. */
  546.  
  547. {
  548.     short                errnum;
  549.     OSType                icondescriptor;
  550.     ProcessSerialNumber    targetpsn;
  551.     AEDesc                targetaddress, propdesc, filedesc, directdesc, icondesc, nulldesc, targetdesc;
  552.     AppleEvent            myae, myreply;
  553.  
  554.     nulldesc.descriptorType = typeNull;
  555.     nulldesc.dataHandle = nil;
  556.  
  557.     icondescriptor = pIconBitmap;
  558.     if (GetFinderProcess(&targetpsn, kAbsoluteFinderPSN) == noErr) 
  559.     {
  560. //        if (usesystemmode)     TurnSystemModeOn();            // you really DON'T want to do this
  561.         
  562.         if ((errnum = AECreateDesc(typeProcessSerialNumber, &targetpsn, sizeof(targetpsn), &targetaddress)) == noErr) {
  563.             if ((errnum = AECreateAppleEvent(kAECoreSuite, kAEGetData, &targetaddress, kAutoGenerateReturnID, kAnyTransactionID, &myae)) == noErr) {
  564.                 if ((errnum = AECreateDesc(typeType, &icondescriptor, sizeof(DescType), &propdesc)) == noErr) {
  565.                     AliasHandle    targetAlias;
  566.                     NewAlias(nil, f, &targetAlias);
  567.                     HLock((Handle)targetAlias);
  568.                     if ((errnum = AECreateDesc(typeAlias, *targetAlias, GetHandleSize((Handle)targetAlias), &filedesc)) == noErr) {
  569.                         if ((errnum = CreateObjSpecifier(typeWildCard, &nulldesc, typeAlias,&filedesc, TRUE, &targetdesc)) == noErr) {
  570.                             if ((errnum = CreateObjSpecifier(cProperty, &targetdesc, formPropertyID, &propdesc, TRUE, &directdesc)) == noErr) {
  571.                                 if ((errnum = AEPutParamDesc(&myae, keyDirectObject, &directdesc)) == noErr) {
  572.                                     errnum = AESend(&myae, &myreply, sendmode, kAENeverInteract, kAEDefaultTimeout, nil, nil);
  573.                                     if (errnum == noErr) {
  574.                                         if (((errnum = AEGetParamDesc(&myreply, keyAEResult, typeWildCard, &icondesc)) == noErr)) {
  575.                                             errnum = AECoerceDesc(&icondesc, typeAERecord, &icondesc);
  576.                                             
  577.                                             {    // copy all the records into our iconfamily
  578.                                                 OSErr        err;
  579.                                                 long        i, numItems;
  580.                                                 AEKeyword    keyWord;
  581.                                                 DescType    theType;
  582.                                                 Size        theSize;
  583.                                                 
  584.                                                 if (!NewIconSuite(iconFamily)) {
  585.                                                     if (!(err = AECountItems(&icondesc, &numItems))) {
  586.                                                         for (i = 1; i <= numItems; i++) {            
  587.                                                             if (!(err = AEGetNthPtr(&icondesc,i,typeWildCard,&keyWord,&theType,
  588.                                                                                     nil,0L,&theSize))) {
  589.                                                                 Handle    buffer = NewHandle(theSize);
  590.                                                                 HLock(buffer);
  591.                                                                 if (!(err = AEGetNthPtr(&icondesc,i,typeWildCard,&keyWord,&theType,
  592.                                                                                         *buffer,GetHandleSize(buffer),&theSize))) {
  593.                                                                     AddIconToSuite(buffer, *iconFamily, keyWord);
  594.                                                                 }
  595.                                                                 // DisposeHandle(buffer);
  596.                                                             }
  597.                                                         }
  598.                                                     }
  599.                                                 }
  600.                                                 
  601.                                             }    
  602.  
  603.                                             AEDisposeDesc(&icondesc);
  604.                                         }
  605.                                     }
  606.                                 }
  607.                                 AEDisposeDesc(&directdesc);
  608.                             }
  609.                         }
  610.                         AEDisposeDesc(&filedesc);
  611.                     }
  612.                     HUnlock((Handle)targetAlias);
  613.                     AEDisposeDesc(&propdesc);
  614.                 }
  615.                 AEDisposeDesc(&myae);
  616.             }
  617.             AEDisposeDesc(&targetaddress);
  618.         }
  619.         
  620. //        if (usesystemmode)     TurnSystemModeOff();            // we really DIDN'T want to do this
  621.     }
  622.     return(errnum);            // the result
  623. }
  624.  
  625.  
  626. OSErr    GetScriptableFinderFileLocation (FSSpec *f, Boolean usesystemmode, AESendMode sendmode, 
  627.                                          Boolean sendToSelf, Rect *r)
  628.  
  629. /*    
  630.  
  631.      Input:    f - FSSpec which contains the item to the position of.
  632.      Input:    usesystemmode - a Boolean which determines whether the system's PPC port will be used.
  633.      Input: sendmode - which mode to send the Apple Event to the Finder.
  634.  
  635.     Output:    error code that occured. */
  636.  
  637. {
  638.     short                errnum;
  639.     OSType                icondescriptor, finderSig = 'MACS';
  640.     ProcessSerialNumber    targetpsn;
  641.     AEDesc                targetaddress, propdesc, filedesc, directdesc, nulldesc, targetdesc, pointdesc;
  642.     AppleEvent            myae, myReply;
  643.     Rect                rect;
  644.     Boolean                fiddlewithA5;            // See below for the usage of the A5 variables
  645.     long                saveA5;
  646.  
  647.  
  648.     nulldesc.descriptorType = typeNull;
  649.     nulldesc.dataHandle = nil;
  650.  
  651.     icondescriptor = pBounds;
  652.     if (GetFinderProcess(&targetpsn, sendToSelf) == noErr) 
  653.     {
  654. //        if (usesystemmode)     TurnSystemModeOn();            // you really DON'T want to do this
  655.         fiddlewithA5 = IsRelativeProcessSerialNumber(&targetpsn);
  656.         if (fiddlewithA5)     saveA5 = SetCurrentA5();
  657.         
  658.         if ((errnum = AECreateDesc(typeProcessSerialNumber, &targetpsn, sizeof(ProcessSerialNumber), &targetaddress)) == noErr) {
  659.             if ((errnum = AECreateAppleEvent(kAECoreSuite, kAEGetData, &targetaddress, kAutoGenerateReturnID, kAnyTransactionID, &myae)) == noErr) {
  660.                 if ((errnum = AECreateDesc(typeType, &icondescriptor, sizeof(DescType), &propdesc)) == noErr) {
  661.                     AliasHandle    targetAlias;
  662.                     NewAlias(nil, f, &targetAlias);
  663.                     HLock((Handle)targetAlias);
  664.                     if ((errnum = AECreateDesc(typeAlias, *targetAlias, GetHandleSize((Handle)targetAlias), &filedesc)) == noErr) {
  665.                         if ((errnum = CreateObjSpecifier(typeWildCard, &nulldesc, typeAlias,&filedesc, TRUE, &targetdesc)) == noErr) {
  666.                             if ((errnum = CreateObjSpecifier(cProperty, &targetdesc, formPropertyID, &propdesc, TRUE, &directdesc)) == noErr) {
  667.                                 if ((errnum = AEPutParamDesc(&myae, keyDirectObject, &directdesc)) == noErr) {
  668.                                     errnum = AESend(&myae, &myReply, sendmode, kAENeverInteract, kAEDefaultTimeout, nil, nil);
  669.                                     if ( errnum == noErr) {
  670.                                         // Get Rect
  671.                                         if (((errnum = AEGetParamDesc(&myReply, keyAEResult, cQDRectangle, &pointdesc)) == noErr))
  672.                                             rect = **((Rect **)(pointdesc.dataHandle));
  673.                                     }
  674.                                 }
  675.                                 
  676.                                 AEDisposeDesc(&directdesc);
  677.                             }
  678.                         }
  679.                         AEDisposeDesc(&filedesc);
  680.                     }
  681.                     HUnlock((Handle)targetAlias);
  682.                     AEDisposeDesc(&propdesc);
  683.                 }
  684.                 AEDisposeDesc(&myae);
  685.             }
  686.             AEDisposeDesc(&targetaddress);
  687.         }
  688.         
  689.         // Get Rect
  690.         *r = rect;
  691.         
  692.         if (fiddlewithA5)     SetA5(saveA5);            // fix it up for crying out loud!
  693. //        if (usesystemmode)     TurnSystemModeOff();            // we really DIDN'T want to do this
  694.     }
  695.     return(errnum);            // the result
  696. }
  697.  
  698. OSErr    GetScriptableFinderTrashLocation (Boolean usesystemmode, AESendMode sendmode, Boolean sendToSelf, Rect *r)
  699.  
  700. /*    
  701.  
  702.      Input:    f - FSSpec which contains the item to the position of.
  703.      Input:    usesystemmode - a Boolean which determines whether the system's PPC port will be used.
  704.      Input: sendmode - which mode to send the Apple Event to the Finder.
  705.  
  706.     Output:    error code that occured. */
  707.  
  708. {
  709.     short                errnum;
  710.     OSType                icondescriptor, trshdescriptor, finderSig = 'MACS';
  711.     ProcessSerialNumber    targetpsn;
  712.     AEDesc                targetaddress, propdesc, trshpropdesc, filedesc, directdesc, nulldesc, targetdesc, pointdesc;
  713.     AppleEvent            myae, myReply;
  714.     Rect                rect;
  715.     Boolean                fiddlewithA5;            // See below for the usage of the A5 variables
  716.     long                saveA5;
  717.  
  718.  
  719.     nulldesc.descriptorType = typeNull;
  720.     nulldesc.dataHandle = nil;
  721.  
  722.     icondescriptor = pBounds;
  723.     trshdescriptor = 'trsh';
  724.     if (GetFinderProcess(&targetpsn, sendToSelf) == noErr) 
  725.     {
  726. //        if (usesystemmode)     TurnSystemModeOn();            // you really DON'T want to do this
  727.         fiddlewithA5 = IsRelativeProcessSerialNumber(&targetpsn);
  728.         if (fiddlewithA5)     saveA5 = SetCurrentA5();
  729.         
  730.         if ((errnum = AECreateDesc(typeProcessSerialNumber, &targetpsn, sizeof(ProcessSerialNumber), &targetaddress)) == noErr) {
  731.             if ((errnum = AECreateAppleEvent(kAECoreSuite, kAEGetData, &targetaddress, kAutoGenerateReturnID, kAnyTransactionID, &myae)) == noErr) {
  732.                 if ((errnum = AECreateDesc(typeType, &icondescriptor, sizeof(DescType), &propdesc)) == noErr) {
  733.                     if ((errnum = AECreateDesc(typeType, &trshdescriptor, sizeof(DescType), &trshpropdesc)) == noErr) {
  734.                         if ((errnum = CreateObjSpecifier(cProperty, &nulldesc, formPropertyID, &trshpropdesc, TRUE, &targetdesc)) == noErr) {
  735.                             if ((errnum = CreateObjSpecifier(cProperty, &targetdesc, formPropertyID, &propdesc, TRUE, &directdesc)) == noErr) {
  736.                                 if ((errnum = AEPutParamDesc(&myae, keyDirectObject, &directdesc)) == noErr) {
  737.                                     errnum = AESend(&myae, &myReply, sendmode, kAENeverInteract, kAEDefaultTimeout, nil, nil);
  738.                                     if ( errnum == noErr) {
  739.                                         // Get Rect
  740.                                         if (((errnum = AEGetParamDesc(&myReply, keyAEResult, cQDRectangle, &pointdesc)) == noErr))
  741.                                             rect = **((Rect **)(pointdesc.dataHandle));
  742.                                     }
  743.                                 }
  744.                                 
  745.                                 if (directdesc.dataHandle)    AEDisposeDesc(&directdesc);
  746.                             }
  747.                         }
  748.                         if (directdesc.dataHandle)    AEDisposeDesc(&trshpropdesc);
  749.                     }
  750.                     if (directdesc.dataHandle)    AEDisposeDesc(&propdesc);
  751.                 }
  752.                 if (directdesc.dataHandle)    AEDisposeDesc(&myae);
  753.             }
  754.             if (directdesc.dataHandle)    AEDisposeDesc(&targetaddress);
  755.         }
  756.         
  757.         // Get Rect
  758.         *r = rect;
  759.         
  760.         if (fiddlewithA5)     SetA5(saveA5);            // fix it up for crying out loud!
  761. //        if (usesystemmode)     TurnSystemModeOff();            // we really DIDN'T want to do this
  762.     }
  763.     return(errnum);            // the result
  764. }